package com.moonbird.springboot.Utils.SpeedTranscription.iflytek;

import com.moonbird.springboot.Utils.SpeedTranscription.request.*;
import com.moonbird.springboot.Utils.SpeedTranscription.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import okhttp3.OkHttpClient;
import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * @author hpl
 */
public class SpeedTranscriptionMain {
    // 控制台获取以下信息
    private static final String APP_ID = "5a0e332b";
    private static final String API_SECRET = "ZTc4NWZiOGFiZmExZTA2YzdmZTgwNzk3";
    private static final String API_KEY = "c830539d43f3e5d4b504c25769e73377";

    // 上传文件的地址前缀
    private static final String FILE_URL_PREFIX = "https://upload-ost-api.xfyun.cn/file";

    // 创建、查询任务的地址前缀
    private static final String OPEN_URL_PREFIX = "https://ost-api.xfyun.cn/v2";
    private static final OkHttpClient client = new OkHttpClient.Builder().build();
    private static final Gson gson = new Gson();

    // 音频文件路径
    private static final String AUDIO_PATH = "src/main/resources/static/audioExample/audio_sample_little.wav";
    // 分块大小 15M
    private static final int SLICE_SIZE = 15728640;

    public static void main(String[] args) throws IOException, InterruptedException {
        // 读取音频文件
        File audio = new File(AUDIO_PATH);
        FileInputStream fis = new FileInputStream(audio);

        // 初始化文件上传客户端
        FileCaller fileCaller = FileCaller.builder()
                .apiKey(API_KEY)
                .apiSecret(API_SECRET)
                .client(client)
                .ulrPrefix(FILE_URL_PREFIX)
                .build();

        JSONObject jsonObjectUploadRespOrCompleteResp;

        /** 1. 上传音频文件 */
        if (audio.length() < 31457280) { // 小于30M的文件
            // 小文件直接上传
            FileResp<FileResp.UploadData> uploadResp = fileCaller.fileUpload(FileReq.Upload.builder()
                    .appId(APP_ID)
                    .fileName("audio_sample_little.wav")
                    .requestId("20211213152023")
                    .data(IOUtils.toByteArray(fis))
                    .build());
            // 获取上传返回的数据
            jsonObjectUploadRespOrCompleteResp = JSON.parseObject(JSON.toJSONString(uploadResp.getData()));
        } else { // 大于30M的文件
            // 分块上传文件
            /** 1.2.1 初始化分块信息 */
            FileResp<FileResp.InitData> initResp = fileCaller.fileInit(FileReq.Init.builder()
                    .requestId("20211213155434")
                    .appId(APP_ID)
                    .build());
            JSONObject jsonObjectInitResp = JSON.parseObject(JSON.toJSONString(initResp.getData()));

            /** 1.2.2 分块上传 */
            // 分片上传文件
            int len;
            byte[] slice = new byte[SLICE_SIZE];
            int sliceIdIndex = 1;
            while ((len = fis.read(slice)) > 0) {
                // 上传分片
                if (fis.available() == 0) {
                    slice = Arrays.copyOfRange(slice, 0, len);
                }
                FileResp<Void> partUploadResp = fileCaller.filePartUpload(FileReq.PartUpload.builder()
                        .requestId("20211213152023")
                        .appId(APP_ID)
                        .uploadId(jsonObjectInitResp.get("upload_id").toString()) // 使用初始化分块信息返回的upload_id
                        .sliceId(sliceIdIndex)
                        .data(slice)
                        .build());
                sliceIdIndex++;
            }

            /** 1.2.3 分块上传完成 */
            FileResp<Void> completeResp = fileCaller.fileUploadComplete(FileReq.Complete.builder()
                    .appId(APP_ID)
                    .requestId("2021164834")
                    .uploadId(jsonObjectInitResp.get("upload_id").toString()) // 使用初始化分块信息返回的upload_id
                    .build());
            // 获取分块上传完成的数据
            jsonObjectUploadRespOrCompleteResp = JSON.parseObject(JSON.toJSONString(completeResp.getData()));
        }

        /** 3. 创建任务 */
        OpenCaller openCaller = OpenCaller.builder()
                .apiKey(API_KEY)
                .apiSecret(API_SECRET)
                .client(client)
                .ulrPrefix(OPEN_URL_PREFIX)
                .build();
        String requestId = "20211213173212"; // 可以自定义
        OpenResp createResp = openCaller.create(OpenReq.Create.builder()
                .common(OpenReq.Common.builder().appId(APP_ID).build())
                .business(OpenReq.Business.builder()
                        .requestId(requestId)
                        // .callbackUrl("http://IP:端口号/xxx")
                        .accent("mandarin")
                        .language("zh_cn")
                        .domain("pro_ost_ed")
                        .build())
                .data(OpenReq.Data.builder()
                        .audioUrl(jsonObjectUploadRespOrCompleteResp.get("url").toString()) // 使用上传文件返回的url
                        .encoding("raw")
                        .format("audio/L16;rate=16000")
                        .audioSrc("http")
                        .build())
                .build());
        JSONObject jsonObjectCreateResp = JSON.parseObject(JSON.toJSONString(createResp.getData()));

        /** 4. 查询任务 */
        OpenResp queryResp = openCaller.query(OpenReq.Query.builder()
                .common(OpenReq.Common.builder().appId(APP_ID).build())
                .business(OpenReq.QueryBusiness.builder().taskId(jsonObjectCreateResp.get("task_id").toString()).build()) // 使用创建任务返回的task_id
                .build());
        JSONObject jsonObjectQueryResp = JSON.parseObject(JSON.toJSONString(queryResp.getData()));

        // 循环查询任务状态，直到任务完成
        while (true) {
            if (jsonObjectQueryResp.get("task_status").equals("5")) {
                // 任务已取消
                break; // 跳出循环
            } else if (jsonObjectQueryResp.get("task_status").equals("3") || jsonObjectQueryResp.get("task_status").equals("4")) {
                // 打印最终转写结果
                JsonParse jsonParse = gson.fromJson(jsonObjectQueryResp.toJSONString(), JsonParse.class);
                List<Lattice> latticeList = jsonParse.result.lattice;
                for (Lattice lattice : latticeList) {
                    List<Rt> rtList = lattice.json_1best.st.rt;
                    for (Rt rt : rtList) {
                        List<Ws> wsList = rt.ws;
                        for (Ws ws : wsList) {
                            List<Cw> cwList = ws.cw;
                            for (Cw cw : cwList) {
                                System.out.print(cw.w);
                            }
                        }
                    }
                }
                break; // 跳出循环
            } else {
                // 两秒查询一次
                Thread.sleep(2000);
                // 再次查询任务
                queryResp = openCaller.query(OpenReq.Query.builder()
                        .common(OpenReq.Common.builder().appId(APP_ID).build())
                        .business(OpenReq.QueryBusiness.builder().taskId(jsonObjectCreateResp.get("task_id").toString()).build()) // 使用创建任务返回的task_id
                        .build());
                jsonObjectQueryResp = JSON.parseObject(JSON.toJSONString(queryResp.getData()));
            }
        }
    }

    /** 解析极速转写结果 */
    public class JsonParse {
        String task_id;
        String task_status;
        String task_type;
        String force_refresh;
        Result result;
    }

    class Result {
        List<Lattice> lattice;
    }

    class Lattice {
        Json_1best json_1best;
    }

    class Json_1best {
        St st;
    }

    class St {
        List<Rt> rt;
        String rl;
    }

    class Rt {
        List<Ws> ws;
    }

    class Ws {
        List<Cw> cw;
    }

    class Cw {
        String w;
    }
}
